#pragma once
#include <string>
#include <iostream>
#include "hash.hpp"

using namespace std;
namespace my_unordered_map
{
	using namespace my_hash;


	template <typename K>
	struct HashFun
	{
		size_t operator()(const K& key)
		{
			return key;
		}
	};
	// 模板特化
	template<>
	struct HashFun<string>
	{
		size_t operator()(const string& key)
		{
			size_t hash = 0;
			for (auto ch : key)
			{
				hash = hash * 31 + ch;
			}
			return hash;
		}
	};

	template <typename K, typename Val>
	struct KeyOfVal
	{
		const K& operator()(const Val& kv)
		{
			return kv.first;
		}
	};

	template <typename K, typename V, typename HashF = HashFun<K>>
	class unordered_map
	{
		typedef Hash<K, std::pair<const K, V>, KeyOfVal<K, std::pair<const K, V>>, HashF> Hash_;

	public:
		typedef typename Hash_::iterator iterator;
		typedef typename Hash_::const_iterator const_iterator;

		std::pair<iterator, bool> insert(const std::pair<K, V>& kv)
		{
			return _hash.insert(kv);
		}
		iterator find(const K& key)
		{
			return _hash.find(key);
		}
		// 返回删除节点的下一个节点
		iterator erase(const_iterator pos)
		{
			return _hash.erase(pos);
		}
		iterator begin()
		{
			return _hash.begin();
		}
		iterator end()
		{
			return _hash.end();

		}
		const_iterator begin() const
		{
			return _hash.begin();
		}
		const_iterator end() const
		{
			return _hash.end();
		}
		V& operator[](const K& key)
		{
			auto res = _hash.insert(make_pair(key, V()));
			return res.first->second;
		}

	private:
		Hash_ _hash;
	};
	void test_map1()
	{
		vector<int> v{ 4,8,10,14,18,20,13,3,33,6,45,5,46 };
		unordered_map<int, int> mp;
		for (auto e : v)
		{
			mp.insert(std::make_pair(e, e));
		}

		auto it = mp.begin();
		while (it != mp.end())
		{
			cout << it->first << " ";
			++it;
		}
		cout << endl;
		auto pos = mp.find(4);
		if (pos == mp.end())
			cout << "no find" << endl;
		else
			cout << "find = " << pos->first << endl;
		auto res = mp.erase(pos);
		if (res != mp.end())
			cout << "next = " << res->first << endl;
		else
			cout << "end" << endl;
	}

	class Date
	{
		// 使用友元，访问内部类私有属性
		friend struct HashDate;
	public:
		Date(int year = 1900, int month = 1, int day = 1)
			: _year(year)
			, _month(month)
			, _day(day)
		{}
		bool operator<(const Date& d)const
		{
			return (_year < d._year) ||
				(_year == d._year && _month < d._month) ||
				(_year == d._year && _month == d._month && _day < d._day);
		}
		bool operator>(const Date& d)const
		{
			return (_year > d._year) ||
				(_year == d._year && _month > d._month) ||
				(_year == d._year && _month == d._month && _day > d._day);
		}
		bool operator==(const Date& d)const
		{
			return _year == d._year && _month == d._month && _day == d._day;
		}
		bool operator!=(const Date& d)const
		{
			return !(*this == d);
		}
		friend ostream& operator<<(ostream& _cout, const Date& d)
		{
			_cout << d._year << "-" << d._month << "-" << d._day;
			return _cout;
		}
	private:
		int _year;
		int _month;
		int _day;
	};
	struct HashDate
	{
		size_t operator()(const Date& d)
		{
			size_t hash = 0;
			hash += d._year;
			hash *= 31;
			hash += d._month;
			hash *= 31;
			hash += d._day;
			hash *= 31;

			return hash;
		}
	};
	void test_map2()
	{
		Date d1(2013, 12, 1);
		Date d2(2013, 11, 2);
		Date d3(2013, 1, 3);
		Date d4(2013, 2, 4);
		Date d5(2013, 5, 5);
		Date d6(2013, 7, 6);
		vector<Date> vd({ d1,d2,d3,d4,d5,d6 });
		unordered_map<Date, Date, HashDate> m;
		for (auto& d : vd)
		{
			m.insert(make_pair(d, d));
		}
		unordered_map<Date, Date, HashDate>::iterator it = m.begin();
		cout << (*it).first << (*it).second << endl;
		cout << it->first << it->second << endl;

	}


	void test_map3()
	{
		unordered_map<string, string> dict;
		dict.insert(make_pair("string", ""));
		dict.insert(make_pair("abc", "a"));
		dict.insert(make_pair("ing", "r"));
		dict.insert(make_pair("str", "h"));

		unordered_map<string, string>::const_iterator it = dict.begin();
		while (it != dict.end())
		{
			cout << it->first << ":" << it->second << endl;
			//it->first = "1111";
			//it->second = "111";
			++it;
		}
		cout << endl;
		for (auto& kv : dict)
		{
			cout << kv.first << ":" << kv.second << endl;
			//it->first = "1111";
			//it->second = "111";
		}
		cout << endl;
	}
	void test_map4()
	{
		string arr[] = { "a","v","a","c","v","e","v","c" };
		unordered_map<string, int> cmp;
		for (auto& e : arr)
		{
			cmp[e]++;
		}
		for (auto& kv : cmp)
		{
			cout << kv.first << "：" << kv.second << endl;
		}

	}


	void test_unordered_map2()
	{
		string arr[] = { "西瓜", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉", "梨" };
		unordered_map<string, int> countMap;
		for (auto& e : arr)
		{
			countMap[e]++;
		}

		for (auto& kv : countMap)
		{
			cout << kv.first << ":" << kv.second << endl;
		}
	}

}